/******************************************************************************* 
  Copyright (C), 1988-2020, zeno Tech. Co., Ltd.
  Description:   AAC模块  
  Function List:     
  History:
    <wangmc -- 2015-04-03>  创建
*******************************************************************************/ 

/*=============================================================================
                                 Includes                                  
 =============================================================================*/
#include "audioPriv.h"
//#define UNSUPPORT_AAC
/*=============================================================================
                               Macro Definition
 =============================================================================*/

/*=============================================================================
                        Local Structures and Typedef 
 =============================================================================*/

/*=============================================================================
                             Extern Variables                                  
=============================================================================*/


/*=============================================================================
                             Local Variables                                  
 =============================================================================*/

/*=============================================================================
                             Function Definition                                  
 =============================================================================*/
#if 0
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
//保存文件到pathname，O_TRUNC表示打开已存在的文件，并清除文件
//len = 0;为关闭文件，使用如:FILE_write("/root/test.dav", pData, dataLen);
int audio_FILE_Write(char *pathname, char *buf, int len) 
{
    static int fd = -1;
    int ret = 0;

    if (fd < 0)
    {
        fd = open(pathname, O_RDWR | O_CREAT | O_TRUNC, 0666);
        if (fd < 0)
        {
            printf("err: open %s fail, try again!\n", pathname);
            return -1;
        }
    }

    if (len == 0)
    {
        close(fd);
        fd = -1;
        printf("close %s\n", pathname);
        return 0;
    }

    ret = write(fd, buf, len);
    if (ret <= 0)
    {
        printf("err: write %s fail\n", pathname);
        return -1;
    }
    return 0;
}

int audio_FILE_Write2(char *pathname, char *buf, int len) 
{
    static int fd = -1;
    int ret = 0;

    if (fd < 0)
    {
        fd = open(pathname, O_RDWR | O_CREAT | O_TRUNC, 0666);
        if (fd < 0)
        {
            printf("err: open %s fail, try again!\n", pathname);
            return -1;
        }
    }

    if (len == 0)
    {
        close(fd);
        fd = -1;
        printf("close %s\n", pathname);
        return 0;
    }

    ret = write(fd, buf, len);
    if (ret <= 0)
    {
        printf("err: write %s fail\n", pathname);
        return -1;
    }
    return 0;
}

int audio_FILE_Write3(char *pathname, char *buf, int len) 
{
    static int fd = -1;
    int ret = 0;

    if (fd < 0)
    {
        fd = open(pathname, O_RDWR | O_CREAT | O_TRUNC, 0666);
        if (fd < 0)
        {
            printf("err: open %s fail, try again!\n", pathname);
            return -1;
        }
    }

    if (len == 0)
    {
        close(fd);
        fd = -1;
        printf("close %s\n", pathname);
        return 0;
    }

    ret = write(fd, buf, len);
    if (ret <= 0)
    {
        printf("err: write %s fail\n", pathname);
        return -1;
    }
    return 0;
}


#endif
/*******************************************************************************
    Function:     AAC_RingbufInit
    Description:  初始化ringbuf
    Input:        - pRingBuf: ringbuf结构体指针
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
static int AAC_RingbufInit(AAC_RINGBUF_t *pRingBuf)
{
	pRingBuf->pBaseAddr = (char *)malloc(AAC_RINGBUF_SIZE);
	if (pRingBuf->pBaseAddr == NULL)
	{
		printf("malloc ringbuf failed!\n");
		return -1;
	}
	pRingBuf->totalSize = AAC_RINGBUF_SIZE;
	pRingBuf->wrOffset = 0;
	pRingBuf->rdOffset = 0;
	pRingBuf->dataLen = 0;

	pthread_mutex_init(&pRingBuf->ringMutex, NULL);
	
	return 0;
}

/*******************************************************************************
    Function:     AAC_RingbufWrite
    Description:  写入数据
    Input:        - pRingBuf: ringbuf结构体指针
                  - pInData: 要写入的数据缓存
                  - dataLen: 要写入的数据长度
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
static int AAC_RingbufWrite(AAC_RINGBUF_t *pRingBuf, char *pInData, int dataLen)
{
	int ret = 0;
	int offset = 0;
	char *pWriteAddr = NULL;

	pthread_mutex_lock(&pRingBuf->ringMutex);
	
	if ((pRingBuf->totalSize - pRingBuf->dataLen) < dataLen)
	{
		LOG_PrintError("The ringbuf is not enough space to write!\n");
		LOG_PrintError("Only %d bytes but need %d bytes!\n",
		                pRingBuf->totalSize - pRingBuf->dataLen, dataLen);
		ret = -1;
		goto mutex_unlock;
	}
	
	offset = pRingBuf->totalSize - pRingBuf->wrOffset;
	pWriteAddr = (char *)(pRingBuf->pBaseAddr + pRingBuf->wrOffset);
	
	if (pRingBuf->wrOffset >= pRingBuf->rdOffset)
	{
		if (offset > dataLen)
		{
			memcpy(pWriteAddr, pInData, dataLen);
			pRingBuf->wrOffset += dataLen;
		}
		else
		{
			memcpy(pWriteAddr, pInData, offset);
			memcpy(pRingBuf->pBaseAddr, 
					(char *)(pInData + offset), dataLen - offset);
			pRingBuf->wrOffset = dataLen - offset;
		}
	}
	else
	{
		memcpy(pWriteAddr, pInData, dataLen);
		pRingBuf->wrOffset += dataLen;
	}
	pRingBuf->dataLen += dataLen;

mutex_unlock:
	pthread_mutex_unlock(&pRingBuf->ringMutex);
	
	return ret;
}

/*******************************************************************************
    Function:     AAC_RingbufRead
    Description:  读出数据
    Input:        - pRingBuf: ringbuf结构体指针
                  - dataLen: 要读出的数据长度
    Output:       - pOutData: 要读出的数据缓存
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
static int AAC_RingbufRead(AAC_RINGBUF_t *pRingBuf, char *pOutData, int dataLen)
{
	int ret = 0;
	int offset = 0;
	char *pReadAddr = NULL;
	
	pthread_mutex_lock(&pRingBuf->ringMutex);
	
	if (pRingBuf->dataLen < dataLen)
	{
		LOG_PrintError("The ringbuf is not enough data to read!\n");
		LOG_PrintError("Only %d bytes but need %d bytes!\n",
                        pRingBuf->dataLen, dataLen);
		ret = -1;
		goto mutex_unlock;
	}
	
	offset = pRingBuf->totalSize - pRingBuf->rdOffset;
	pReadAddr = (char *)(pRingBuf->pBaseAddr + pRingBuf->rdOffset);
	
	if (pRingBuf->wrOffset > pRingBuf->rdOffset)
	{
		memcpy(pOutData, pReadAddr, dataLen);
		pRingBuf->rdOffset += dataLen;
	}
	else
	{
		if (offset > dataLen)
		{
			memcpy(pOutData, pReadAddr, dataLen);
			pRingBuf->rdOffset += dataLen;
		}
		else
		{
			memcpy(pOutData, pReadAddr, offset);
			memcpy((char *)(pOutData + offset), 
					pRingBuf->pBaseAddr, dataLen - offset);
			pRingBuf->rdOffset = dataLen - offset;
		}
	}
	pRingBuf->dataLen -= dataLen;

mutex_unlock:
	pthread_mutex_unlock(&pRingBuf->ringMutex);
	
	return ret;
}

/*******************************************************************************
    Function:     AAC_RingbufDestroy
    Description:  注销ringbuf
    Input:        - pRingBuf: ringbuf结构体指针
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
static int AAC_RingbufDestroy(AAC_RINGBUF_t *pRingBuf)
{
	free(pRingBuf->pBaseAddr);
	pRingBuf->totalSize = 0;
	pRingBuf->wrOffset = 0;
	pRingBuf->rdOffset = 0;
	pRingBuf->dataLen = 0;

	return 0;
}

#ifdef OPEN_SOURCE_AAC
/*******************************************************************************
    Function:     AAC_EncThread
    Description:  AAC音频编码线程
    Input:        - arg: 线程输入参数
    Output:       无
    Return:       NULL
    Others:       无
*******************************************************************************/
static void *AAC_EncThread(void *arg)
{
    int ret;
    int outBufLen;
    unsigned int sequence = 0;
	AAC_ctl_t *pAacCtl;
	RINGBUF_block_t blockBuf;
	AAC_aencStream_t aencStream;
	struct timespec tempTime;
    SYS_thdInfo_t thdInfo;
    
	pAacCtl = (AAC_ctl_t *)arg;

    strcpy(thdInfo.name, "aacEncThd");
    ret = SYS_DebugRegThd(&thdInfo);
    if (ret < 0)
    {
        LOG_PrintError("Fail to register cmd thread!\n");
    }

	while (1)
	{
	    if(pAacCtl->aacStart == 0)
	    {
            usleep(50*1000);
            continue;
	    }
	    
		if (pAacCtl->ringBuf.dataLen >= pAacCtl->maxInputBytes)
	    {
	        ret = AAC_RingbufRead(&pAacCtl->ringBuf, 
                                 pAacCtl->pPcmBuffer, 
                                 pAacCtl->maxInputBytes);
            if (ret)
            {
                LOG_PrintError("read buf failed!\n");
                continue;
            }

            clock_gettime(CLOCK_MONOTONIC, &tempTime);

            
            AUDIO_RingbufGet(pAacCtl->hRingBuf, pAacCtl->maxOutputBytes, &blockBuf);
            
            outBufLen = faacEncEncode(pAacCtl->hEncoder, 
                                        (int *)pAacCtl->pPcmBuffer, 
                                        pAacCtl->inputSamples, 
                                        (unsigned char *)blockBuf.bufAddr, 
                                        pAacCtl->maxOutputBytes);
        	if (outBufLen < 1)
        	{
        	    LOG_PrintWarn("aac encode failed!,outBufLen=%d\n", outBufLen);
        	    if (AUDIO_RingbufPut(pAacCtl->hRingBuf, &blockBuf))
            	{
            	    LOG_PrintWarn("Fail to put ring buf!\n");
            	}
        		continue;
        	}

            aencStream.pData = (unsigned char *)blockBuf.bufAddr;
            aencStream.dataSize = outBufLen;
            aencStream.sequence = ++sequence;
            aencStream.tvSec = tempTime.tv_sec;
            aencStream.tvUsec = tempTime.tv_nsec/1000;
        	if (AUDIO_QueueWriteData(pAacCtl->hQueue, (void *)&aencStream))
        	{
        	    LOG_PrintError("Fail to write to queue!\n");
        	    continue;
        	}
            
		}
		else
		{
			usleep(20*1000); //时间待测试 todo
		}
	}
    
    ret = SYS_DebugUnRegThd();
    if (ret < 0)
    {
        LOG_PrintError("Fail to unregister cmd thread!\n");
    }
    
    return NULL;
}

/*******************************************************************************
    Function:     AAC_EncCreat
    Description:  创建AAC音频编码资源
    Input:        - pAacCfg: 音频信息配置
    Output:       无
    Return:       !NULL: 操作成功
                  NULL: 操作失败
    Others:       无
*******************************************************************************/
void *AAC_EncCreat(AAC_audioCfg_t *pAacCfg)
{
    if (!pAacCfg)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return NULL;
	} 

    AAC_ctl_t * pAacCtl = (AAC_ctl_t *)malloc(sizeof(AAC_ctl_t));
    if (!pAacCtl)
    {
        LOG_PrintError("Fail to malloc memory.\n");
        return NULL;
    }

    int ret = 0;
    
    /* 初始化aac句柄，同时获取最大输入样本，及编码所需最小字节 */
    pAacCtl->hEncoder = faacEncOpen(pAacCfg->sampleRate, 
                                    pAacCfg->channels, 
                                    &pAacCtl->inputSamples, 
                                    &pAacCtl->maxOutputBytes);

    /* 计算最大输入字节,根据最大输入样本数 */
    pAacCtl->maxInputBytes = pAacCtl->inputSamples*pAacCfg->bitWidth/8;
    

    //LOG_PrintError("maxInputBytes=%u,maxOutputBytes=%u \n",pAacCtl->maxInputBytes,pAacCtl->maxOutputBytes);

    pAacCtl->pPcmBuffer = (char *)malloc(pAacCtl->maxInputBytes);
    if (!pAacCtl->pPcmBuffer)
    {
        LOG_PrintError("Fail to malloc memory.\n");
        free(pAacCtl);
        return NULL;
    }
    
    pAacCtl->hQueue = AUDIO_QueueCreate(128, sizeof(AAC_aencStream_t));
    if (!pAacCtl->hQueue)
    {
        LOG_PrintError("Fail to creat queue!\n");
        goto free_ctl;
    }
    
	pAacCtl->hRingBuf = AUDIO_RingbufInit(128*pAacCtl->maxOutputBytes);
	if (!pAacCtl->hRingBuf)
    {
        LOG_PrintError("Fail to init ringbuf!\n");
        goto free_ctl;
    }

    ret = AAC_RingbufInit(&pAacCtl->ringBuf);
    if (ret)
    {
        LOG_PrintError("ringbuf init failed \n");
        goto free_ctl;
    }

	pAacCtl->aacStart = 0;
	
    ret= pthread_create(&pAacCtl->aencPtid, NULL, AAC_EncThread, (void *)pAacCtl);
	if (ret != 0)
	{
		LOG_PrintError("can't create thread: %s\n", strerror(ret));
		goto free_ctl;
	}

	LOG_PrintWarn("AAC_EncCreat success\n");
    
    return (void *)pAacCtl;

free_ctl: 
    free(pAacCtl->pPcmBuffer);
    free(pAacCtl);  
    return NULL;
}

/*******************************************************************************
    Function:     AAC_EncSetFormat
    Description:  创建AAC音频编码格式
    Input:        - hAac: AAC句柄
    Output:       无
    Return:       !NULL: 操作成功
                  NULL: 操作失败
    Others:       0: 操作成功
                  -1: 操作失败
*******************************************************************************/
int AAC_EncSetFormat(void *hAac, AAC_audioCfg_t *pAacCfg)
{
    if (!hAac || !pAacCfg)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	} 
	
    int ret = 0;
    AAC_ctl_t *pAacCtl;
    faacEncConfigurationPtr pConfiguration; /*aac设置指针*/ 

    pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}  

    /*获取配置结构指针*/
    pConfiguration = faacEncGetCurrentConfiguration(pAacCtl->hEncoder);
    if (!pConfiguration)
	{
		LOG_PrintError("pConfiguration is NULL.\n");
		return -1;
	}

	//LOG_PrintWarn("pAacCfg outputFormat=%d, bitrate=%d\n", pAacCfg->outputFormat, pAacCfg->sampleRate);
    
    pConfiguration->inputFormat = FAAC_INPUT_16BIT;
	pConfiguration->outputFormat = pAacCfg->outputFormat;
	pConfiguration->useTns = 0;
	pConfiguration->useLfe = 0;
	pConfiguration->aacObjectType = LOW;
	pConfiguration->shortctl = SHORTCTL_NORMAL;
	pConfiguration->quantqual = 0;
	pConfiguration->bandWidth = 0;
	pConfiguration->bitRate = pAacCfg->sampleRate;
	
    /*设置配置，根据不同设置，耗时不一样*/
    int result = faacEncSetConfiguration(pAacCtl->hEncoder, pConfiguration);
    if (result == 0)
	{
		LOG_PrintError("faacEncSetConfiguration failed.\n");
		return -1;
	}

	memcpy(&pAacCtl->aacCfg, pAacCfg, sizeof(AAC_audioCfg_t));

	LOG_PrintWarn("AAC_EncSetFormat success\n");
    
    return ret;
}

/*******************************************************************************
    Function:     AAC_EncStart
    Description:  启动AAC音频编码格式
    Input:        - hAac: AAC句柄
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
*******************************************************************************/
int AAC_EncStart(void *hAac)
{
    int ret = 0;
    AAC_ctl_t *pAacCtl;

    pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

	pAacCtl->aacStart = 1;

	return 0;
}
/*******************************************************************************
    Function:     AAC_EncStop
    Description:  关闭AAC音频编码格式
    Input:        - hAac: AAC句柄
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
*******************************************************************************/
int AAC_EncStop(void *hAac)
{
    int ret = 0;
    AAC_ctl_t *pAacCtl;

    pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

	pAacCtl->aacStart = 0;

	return 0;
}

/*******************************************************************************
    Function:     AAC_EncSendFrame
    Description:  发送音频数据至AAC编码线程
    Input:        - hAac: AAC句柄
                  - pInData: 输入数据指针
                  - dataLen: 输入数据长度
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncSendFrame(void *hAac, char *pInData, int dataLen)
{
	int ret;
	AAC_ctl_t *pAacCtl;

	pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

	ret = AAC_RingbufWrite(&pAacCtl->ringBuf, pInData, dataLen);
    if (ret)
    {
        LOG_PrintError("write buf failed!\n");
		return -1;
    }

	return 0;
}

/*******************************************************************************
    Function:     AAC_EncGetStream
    Description:  获取AAC音频编码数据
    Input:        - hAac: AAC句柄
    Output:       - pAencStream:编码信息结构体指针
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncGetStream(void *hAac, AAC_aencStream_t *pAencStream)
{
	AAC_ctl_t *pAacCtl;

	pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

	return AUDIO_QueueReadData(pAacCtl->hQueue, (void *)pAencStream);
}

/*******************************************************************************
    Function:     AAC_EncReleaseStream
    Description:  释放AAC音频编码数据
    Input:        - hAac: AAC句柄
                  - pAencStream:编码信息结构体指针
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncReleaseStream(void *hAac, AAC_aencStream_t *pAencStream)
{
    RINGBUF_block_t blockBuf;
    AAC_ctl_t *pAacCtl;

	pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

    blockBuf.bufAddr = (unsigned int)pAencStream->pData;
    blockBuf.bufSize = pAacCtl->maxOutputBytes;
	if (AUDIO_RingbufPut(pAacCtl->hRingBuf, &blockBuf))
	{
	    LOG_PrintError("Fail to put ring buf!\n");
	    return -1;
	}
	
    return 0;
}

/*******************************************************************************
    Function:     AAC_EncDestroy
    Description:  销毁AAC音频编码资源
    Input:        - hAac: AAC句柄
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncDestroy(void *hAac)
{
    int ret;
	AAC_ctl_t *pAacCtl;

	pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

    pAacCtl->aacStart = 0;
    
    pthread_join(pAacCtl->aencPtid, 0);

    faacEncClose(pAacCtl->hEncoder);
    
    free(pAacCtl->pPcmBuffer);

    ret = AAC_RingbufDestroy(&pAacCtl->ringBuf);
    if (ret)
    {
        LOG_PrintError("ringbuf destroy failed \n");
        return -1;
    }

    ret = AUDIO_RingbufDeInit(pAacCtl->hRingBuf);
    if (ret)
    {
        LOG_PrintError("ringbuf destroy failed \n");
        return -1;
    }

    ret = AUDIO_QueueDestroy(pAacCtl->hQueue);
    if (ret)
    {
        LOG_PrintError("queue destroy failed \n");
        return -1;
    }

    free(pAacCtl);

    return 0;
}

/*******************************************************************************
    Function:     AAC_EncGetDecSpecificInfo
    Description:  获取AAC编码数据需要的解码信息
    Input:        - hAac: AAC句柄
    Output:       - ppBuffer 解码信息裸指针的指针
                  - pSize 解码信息长度
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncGetDecSpecificInfo(void *hAac, char **ppBuffer, unsigned long *pSize)
{
    int ret;
	AAC_ctl_t *pAacCtl;

	pAacCtl = (AAC_ctl_t *)hAac;
	if (!pAacCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

    ret = faacEncGetDecoderSpecificInfo(pAacCtl->hEncoder, ppBuffer, pSize);
    if (ret)
    {
        LOG_PrintError("faacEncGetDecoderSpecificInfo failed \n");
        return -1;
    }

    return 0;
}

#else
/*******************************************************************************
    Function:     AAC_EncCreat
    Description:  创建AAC音频编码资源
    Input:        - pAacCfg: 音频信息配置
    Output:       无
    Return:       !NULL: 操作成功
                  NULL: 操作失败
    Others:       无
*******************************************************************************/
void *AAC_EncCreat(AAC_audioCfg_t *pAacCfg)
{
    return NULL;
}

/*******************************************************************************
    Function:     AAC_EncDestroy
    Description:  销毁AAC音频编码资源
    Input:        - hAac: AAC句柄
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncDestroy(void *hAac)
{
    return 0;
}

/*******************************************************************************
    Function:     AAC_EncSendFrame
    Description:  发送音频数据至AAC编码线程
    Input:        - hAac: AAC句柄
                  - pInData: 输入数据指针
                  - dataLen: 输入数据长度
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncSendFrame(void *hAac, char *pInData, int dataLen)
{
     return 0;
}

/*******************************************************************************
    Function:     AAC_EncGetStream
    Description:  获取AAC音频编码数据
    Input:        - hAac: AAC句柄
    Output:       - pAencStream:编码信息结构体指针
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncGetStream(void *hAac, AAC_aencStream_t *pAencStream)
{
     return 0;
}

/*******************************************************************************
    Function:     AAC_EncReleaseStream
    Description:  释放AAC音频编码数据
    Input:        - hAac: AAC句柄
                  - pAencStream:编码信息结构体指针
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_EncReleaseStream(void *hAac, AAC_aencStream_t *pAencStream)
{
     return 0;
}
#endif

/*******************************************************************************
    Function:     AAC_DecCreat
    Description:  创建AAC音频解码资源
    Input:        - bitWidth: 位宽
    Output:       无
    Return:       !NULL: 操作成功
                  NULL: 操作失败
    Others:       无
*******************************************************************************/
void *AAC_DecCreat()
{   
#ifdef UNSUPPORT_AAC
    return NULL;
#else
    int ret;
    AAD_ctl_t *pAadCtl;

    pAadCtl = (AAD_ctl_t *)malloc(sizeof(AAD_ctl_t));
    if (!pAadCtl)
    {
        LOG_PrintError("Fail to malloc memory.\n");
        return NULL;
    }

    pAadCtl->isInitAad = 1;
    
    /*open decoder*/  
    pAadCtl->hDecoder = NeAACDecOpen();


    ret = AAC_RingbufInit(&pAadCtl->ringBuf);
    if (ret)
    {
        LOG_PrintError("ringbuf init failed \n");
        return NULL;
    }


    pAadCtl->maxOutputBytes = 512; //初始化512字节
    
    return (void *)pAadCtl;
#endif
}

/*******************************************************************************
    Function:     AAC_DecSetFormat
    Description:  创建AAC音频解码格式
    Input:        - hAac: AAC句柄
    Output:       无
    Return:       !NULL: 操作成功
                  NULL: 操作失败
    Others:       0: 操作成功
                  -1: 操作失败
*******************************************************************************/
int AAC_DecSetFormat(void *hAad, AAC_audioCfg_t *pAadCfg)
{
    if (!hAad || !pAadCfg)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	} 
	
    int ret = 0;
    AAD_ctl_t *pAadCtl;
    pAadCtl = (AAD_ctl_t *)hAad;
	if (!pAadCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

	pAadCtl->bitWidth = pAadCfg->bitWidth;

	NeAACDecConfigurationPtr decConfig; /*aac设置指针*/ 

   /*Get the current config*/
    decConfig = NeAACDecGetCurrentConfiguration(pAadCtl->hDecoder);

    decConfig->defObjectType = LC;
    decConfig->defSampleRate = pAadCfg->sampleRate; //8000
    decConfig->dontUpSampleImplicitSBR = 1;
    decConfig->outputFormat = FAAD_FMT_16BIT;
    
    /*Set the new configuration*/
    NeAACDecSetConfiguration(pAadCtl->hDecoder, decConfig);

	memcpy(&pAadCtl->aadCfg, pAadCfg, sizeof(AAC_audioCfg_t));

	LOG_PrintWarn("AAC_DecSetFormat success\n");
    
    return ret;
}


/*******************************************************************************
    Function:     AAC_DecSendFrame
    Description:  发送音频数据至AAC解码
    Input:        - hAad: 解码句柄
                  - pInBuf: 输入音频数据缓存
                  - inBufLen: 输入音频数据长度
    Output:       无
    Return:       >0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_DecSendFrame(void *hAad, char *pInBuf, int inBufLen)
{ 
#ifdef UNSUPPORT_AAC
    return -1;
#else
    char* pPcmData = NULL;
    int ret, pcmDataLen;
	AAD_ctl_t *pAadCtl;
    NeAACDecFrameInfo frameInfo; 

	pAadCtl = (AAD_ctl_t *)hAad;
	if (!pAadCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}

    memset(&frameInfo, 0, sizeof(frameInfo));
    
    if (1 == pAadCtl->isInitAad)
    {
        unsigned long samplerate;
        unsigned char channels;
    
        NeAACDecInit(pAadCtl->hDecoder, (unsigned char *)pInBuf, 
                            (unsigned long)inBufLen, &samplerate, &channels); // 注意，首次解码不会解出任何数据，也没有错误，应该是解码器内部初始化）
        
        pAadCtl->isInitAad = 0;

        LOG_PrintInfo("NeAACDecInit, fsamplerate=%d,channels=%d\n",samplerate,channels);   
    }

    pPcmData = (char*)NeAACDecDecode(pAadCtl->hDecoder, &frameInfo, 
                                        (unsigned char *)pInBuf, 
                                        (unsigned long)inBufLen);   //如果你提供的AAC数据较多，那么可能会分几次解出PCM数据??
    if(frameInfo.error > 0)  
    {  
        LOG_PrintError("NeAACDecDecode:%s , inBufLen=%d\n",NeAACDecGetErrorMessage(frameInfo.error), inBufLen);              
        return -1;
    }
    else if(pPcmData && (frameInfo.samples > 0))
    {  
        pcmDataLen = frameInfo.samples*pAadCtl->bitWidth/8; // 实际解出的PCM数据需要将样本数和通道数相乘??

        /* 最大输出字节*/
        pAadCtl->maxOutputBytes = pcmDataLen;        
    }
    else
    {
        //LOG_PrintError("Fail to aac decode, frameInfo.samples=%d,frameInfo.error=%d\n",frameInfo.samples, frameInfo.error);          
        return -1;
    }

    //LOG_PrintWarn("decode inBufLen=%d, pcmDataLen =%d, ringBuf.dataLen=%d!\n",inBufLen, pcmDataLen, pAadCtl->ringBuf.dataLen);

    ret = AAC_RingbufWrite(&pAadCtl->ringBuf, pPcmData, pcmDataLen);
    if (ret)
    {
        //LOG_PrintError("write to ringbuf failed! frameInfo.samples=%d,frameInfo.error=%d\n",frameInfo.samples, frameInfo.error);
		return -1;
    }
    
    return pAadCtl->ringBuf.dataLen;
#endif
}

/*******************************************************************************
    Function:     AAC_DecGetStream
    Description:  获取AAC解码数据
    Input:        - hAad: 解码句柄
                  - inBufLen: 输出音频数据长度
    Output:       - pData: 输出音频数据缓存
    Return:       >0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_DecGetStream(void *hAad, char *pData, int dataLen)
{
#ifdef UNSUPPORT_AAC
    return -1;
#else
    int ret;
    AAD_ctl_t *pAadCtl;

	pAadCtl = (AAD_ctl_t *)hAad;
	if (!pAadCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}
	
    ret = AAC_RingbufRead(&pAadCtl->ringBuf, pData, dataLen);
    if (ret)
    {
        LOG_PrintError("read from ringbuf failed!\n");
		return -1;
    }

    return pAadCtl->ringBuf.dataLen;
#endif
}

/*******************************************************************************
    Function:     AAC_DecDestroy
    Description:  销毁AAC音频解码资源
    Input:        - hAad: 解码句柄
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AAC_DecDestroy(void *hAad)
{
#ifdef UNSUPPORT_AAC
    return -1;
#else
    int ret;
    AAD_ctl_t *pAadCtl;

	pAadCtl = (AAD_ctl_t *)hAad;
	if (!pAadCtl)
	{
		LOG_PrintError("Input parameter is NULL.\n");
		return -1;
	}
	
    NeAACDecClose(pAadCtl->hDecoder);

    pAadCtl->isInitAad = 0;

    ret = AAC_RingbufDestroy(&pAadCtl->ringBuf);
    if (ret)
    {
        LOG_PrintError("ringbuf destroy failed \n");
        return -1;
    }
    
    return 0;
#endif
}
